﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core.Lister;
using COFE.Core;
using NUnit.Framework;
using System.IO;
using COFE.Core.Profile;

namespace COFE.Core.UnitTest
{
    public abstract class TestDirectoryLister<T> : IUnitTest where T : IDirectoryLister
    {
        #region Constructor

        public TestDirectoryLister(T directoryLister, string rootTestPath)
        {
            Assert.IsNotNull(directoryLister);
            Assert.IsNotNull(rootTestPath);
            Assert.IsNotNullOrEmpty(directoryLister.ListerKey);

            _directoryLister = directoryLister;
            if (String.IsNullOrEmpty(rootTestPath))
                rootTestPath = COFEPath.FormatFullParseName(directoryLister.ListerKey, "");
            rootTestPath = COFEPath.Combine(rootTestPath, "Test");
            _rootTestPath = rootTestPath;
            
            _userProfile = UserProfile.Create("TestUser", false);
            _userProfile.RegisterVolume(_directoryLister);

            if (_userProfile.Directory.Exists(_rootTestPath))
                _userProfile.Directory.Delete(_rootTestPath);
            _userProfile.Directory.CreateDirectory(_rootTestPath);

            //{TestDL}Test
            _rootTest = _userProfile.TryParsePath(
                COFEPath.FormatFullParseName(_directoryLister.ListerKey, _rootTestPath)) as IInternalDirectoryInfoExA;  
            Assert.IsNotNull(_rootTest);
            _rootTestPath = _rootTest.ParseName;
        }

        
        #endregion

        #region Methods

        public virtual void CleanUp()
        {
            foreach (var fsi in _rootTest.EnumerateFileSystemInfos())
                fsi.Delete();
        }

        public virtual void CreateDirectories()
        {
            _rootTest.CreateDirectory("A").CreateDirectory("B").CreateDirectory("C").CreateDirectory("D");
            Assert.IsNotNull(_rootTest["A"]);
            Assert.IsNotNull(_rootTest["A"]["B"]);
            Assert.IsNotNull(_rootTest["A"]["B"]["C"]);
            Assert.IsNotNull(_rootTest["A"]["B"]["C"]["D"]);
            Assert.IsNotNull(_userProfile.TryParsePath(_rootTest["A"]["B"]["C"]["D"].ParseName));
        }

        string f = "text.txt";
        string f1 = "text1.txt";

        public virtual void CreateFiles()
        {
            Action<IDirectoryInfo, string> createFile = (parent, fileName) =>
                {
                    string filePath = COFEPath.Combine(parent.ParseName, fileName);
                    Assert.IsFalse(_userProfile.File.Exists(filePath));
                    using (var sw = new StreamWriter(_userProfile.File.Create(filePath)))
                        sw.Write(filePath);
                    Assert.IsTrue(_userProfile.File.Exists(filePath));
                    using (var sr = new StreamReader(_userProfile.File.OpenRead(filePath)))
                        Assert.AreEqual(filePath, sr.ReadToEnd());
                };            
            createFile(_rootTest, f);
            createFile(_rootTest["A"], f);
            createFile(_rootTest["A"]["B"], f);
            createFile(_rootTest["A"]["B"]["C"], f);
            createFile(_rootTest["A"]["B"]["C"]["D"], f);
        }

        public virtual void CopyFiles()
        {
            Action<IFileInfo, IDirectoryInfo, string> copyFile = (file, targetDir, newName) =>
                {
                    string targetName = COFEPath.Combine(targetDir.ParseName, newName);
                    Assert.IsTrue(file.Exists);
                    Assert.IsFalse(_userProfile.File.Exists(targetName));
                    _userProfile.File.Copy(file.ParseName, targetName);
                    Assert.IsTrue(_userProfile.File.Exists(targetName));
                };

            copyFile(_rootTest["A"]["B"]["C"]["D"][f, true] as IFileInfo, _rootTest["A"]["B"]["C"]["D"], f1);
            copyFile(_rootTest["A"]["B"]["C"]["D"][f, true] as IFileInfo, _rootTest["A"]["B"]["C"], f1);
        }

        public virtual void RemoveFiles()
        {
            Assert.IsNotNull(_rootTest["A"]["B"]["C"]["D"][f, true]);
            _rootTest["A"]["B"]["C"]["D"][f, true].Delete();
            Assert.IsNull(_rootTest["A"]["B"]["C"]["D"][f, true]);
            var dtxt = COFEPath.Combine(_rootTest["A"]["B"]["C"]["D"].ParseName, f);
            Assert.IsFalse(_userProfile.File.Exists(dtxt));

            var ctxt = COFEPath.Combine(_rootTest["A"]["B"]["C"].ParseName, f);
            Assert.IsTrue(_userProfile.File.Exists(ctxt));                    
            _userProfile.File.Delete(ctxt);
            Assert.IsFalse(_userProfile.File.Exists(ctxt));            
        }

        public virtual void RemoveDirectories()
        {
            Assert.IsNotNull(_rootTest["A"]["B"]["C"]);
            _rootTest["A"]["B"]["C"].Delete();
            Assert.IsNull(_rootTest["A"]["B"]["C"]);
            Assert.IsNull(_userProfile.TryParsePath(COFEPath.Combine(_rootTest.ParseName, "A\\B\\C\\D"), EntryConstructionFlags.DefaultWithoutCache));
        }

        public virtual void PollDirectoryProperties()
        {
            IInternalDirectoryInfoExA dir = _rootTest["A"] as IInternalDirectoryInfoExA;
            Assert.IsNotNull(dir);
            foreach (var p in dir.GetSupportedProperty())
                dir.GetProperty(p);
        }

        public virtual void PollFileProperties()
        {
            IInternalFileInfoExA file = _rootTest["A"][f, true] as IInternalFileInfoExA;
            Assert.IsNotNull(file);
            foreach (var p in file.GetSupportedProperty())
                file.GetProperty(p);
        }

        public virtual void Root_s_Parent_Equals_Null()
        {            
            Assert.AreEqual(_rootTest, _rootTest["A"].Parent);
            var dir = _rootTest;
            while (dir != null)
            {
                string dirName = dir.Name;
                dir = dir.Parent as IInternalDirectoryInfoExA;
            }
        }

        [Test]
        public virtual void Test()
        {
            CleanUp();
            CreateDirectories();
            CreateFiles();
            CopyFiles();
            PollFileProperties();
            PollDirectoryProperties();
            RemoveFiles();
            RemoveDirectories();

            Root_s_Parent_Equals_Null();
        }

        #endregion

        #region Data
        
        protected IUserProfile _userProfile;
        protected T _directoryLister;
        protected string _rootTestPath;
        protected IInternalDirectoryInfoExA _rootTest;

        #endregion

        #region Public Properties

        #endregion

    }
}
